package nc.vo.scm.plugin;

import java.io.File;
import java.util.ArrayList;
import nc.bs.framework.ServiceConfig;
import nc.bs.framework.common.RuntimeEnv;
import nc.ui.scm.service.LocalCallService;
import nc.vo.cache.CacheManager;
import nc.vo.cache.ICache;
import nc.vo.cache.config.CacheConfig;
import nc.vo.jcom.lang.StringUtil;
import nc.vo.jcom.xml.XMLUtil;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.scm.pub.SCMEnv;
import nc.vo.scm.pub.smart.SmartFieldMeta;
import nc.vo.scm.service.ServcallVO;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class ScmPluginXML
{
  public static final String TAG_PLUGIN_IC = "scm_plugin_ic";
  public static final String TAG_VO_FIELD_EXTEND = "vo_field_extend";
  public static final String TAG_CBILLTYEPCODE = "cbilltypecode";
  public static final String TAG_FIELDS = "fields";
  public static final String TAG_VOCLASSNAME = "voclassname";
  public static final String TAG_FIELD = "field";
  public static final String TAG_DBFIELDNAME = "dbfieldname";
  public static final String TAG_VOFIELDNAME = "vofieldname";
  public static final String TAG_DBFIELDTYPE = "dbfieldtype";
  public static final String TAG_VOFIELDTYPE = "vofieldtype";
  public static final String TAG_PERSISTENCE = "persistence";
  public static final String TAG_PRECISION = "precision";
  public static final String TAG_LENGTH = "length";
  public static final String TAG_ALLOWNULL = "allownull";
  public static final String TAG_SHOWPROP = "showprop";
  public static final String TAG_SHOWNAME = "showname";
  public static final String TAG_ISSHOW = "isshow";
  public static final String TAG_TABCODE = "tabcode";
  public static final String TAG_SHOWFORMULA = "showformula";
  public static final String TAG_LOADFORMULA = "loadformula";
  public static final String TAG_REFTYPE = "reftype";
  public static final String TAG_UI_EXTEND = "ui_extend";
  public static final String TAG_NODECODE = "nodecode";
  public static final String TAG_EXTENDUICLASSNAME = "extenduiclassname";
  public static final String TAG_MENUS = "menus";
  public static final String TAG_MENU = "menu";
  public static final String TAG_NAME = "name";
  public static final String TAG_CODE = "code";
  public static final String TAG_HOTKEY = "hotkey";
  public static final String TAG_RESID = "resid";
  public static final String TAG_PARENTMENUCODE = "parentmenucode";
  public static final String TAG_UIPLUGIN = "uiplugin";
  public static final String TAG_CLASSNAME = "classname";
  public static final String TAG_MOTHED = "mothed";
  public static final String TAG_LOCATION = "location";
  public static final String TAG_BS_EXTEND = "bs_extend";
  public static final String TAG_BSPLUGINCLASSNAME = "bspluginclassname";
  private static Document m_doc;
  public static final String m_filePath = RuntimeEnv.getInstance().getNCHome() + ServiceConfig.getFileSeparator() + "ierp" + ServiceConfig.getFileSeparator() + "bin" + ServiceConfig.getFileSeparator() + "scmplugin.xml";
  private static ScmPluginXML scmpluginxml;

  private ScmPluginXML()
  {
    retrieveDoc();
  }

  public static Document getScmPluginXML()
  {
    try
    {
      if (!new File(m_filePath).exists()) {
        return null;
      }
      return XMLUtil.getDocument(m_filePath);
    } catch (Throwable e) {
      SCMEnv.error(e);
    }
    return null;
  }

  public BSPluginsInfo[] getExtBSPlugins(String prodcode, String cbilltype)
    throws BusinessException
  {
    if ((prodcode == null) || (cbilltype == null))
      return null;
    if (m_doc == null)
      return null;
    Element el = XMLUtil.getElement(m_doc, "scm_plugin_" + prodcode.trim().toLowerCase(), 0);
    if (el == null)
      return null;
    NodeList nodelist = el.getElementsByTagName("bs_extend");
    if ((nodelist == null) || (nodelist.getLength() <= 0))
      return null;
    Node nd = null;

    ArrayList listsf = new ArrayList();
    BSPluginsInfo pinfo = null;
    for (int i = 0; i < nodelist.getLength(); ++i) {
      nd = nodelist.item(i);
      String stemp = XMLUtil.getChildNodeValueOf(nd, "cbilltypecode");
      if (!StringUtil.isEmpty(stemp))
        if (cbilltype.equals(stemp.trim())) {
          stemp = XMLUtil.getChildNodeValueOf(nd, "bspluginclassname");
          if (!StringUtil.isEmpty(stemp)) {
            pinfo = new BSPluginsInfo();
            pinfo.setBspluginclassname(stemp.trim());
            pinfo.setCbilltypecode(cbilltype);
            pinfo.setNodecode(XMLUtil.getChildNodeValueOf(nd, "nodecode"));

            listsf.add(pinfo);
          }
        }
    }
    if (listsf.size() <= 0)
      return null;
    return (BSPluginsInfo[])listsf.toArray(new BSPluginsInfo[listsf.size()]);
  }

  public UIPluginsInfo[] getExtUIPlugins(String prodcode, String cbilltype, String uiclassname)
    throws BusinessException
  {
    if ((prodcode == null) || ((cbilltype == null) && (uiclassname == null)))
      return null;
    if (m_doc == null)
      return null;
    Element el = XMLUtil.getElement(m_doc, "scm_plugin_" + prodcode.trim().toLowerCase(), 0);
    if (el == null)
      return null;
    NodeList nodelist = el.getElementsByTagName("ui_extend");
    if ((nodelist == null) || (nodelist.getLength() <= 0))
      return null;
    Node nd = null;

    ArrayList listsf = new ArrayList();
    UIPluginsInfo pinfo = null;
    for (int i = 0; i < nodelist.getLength(); ++i) {
      nd = nodelist.item(i);
      String stemp = XMLUtil.getChildNodeValueOf(nd, "cbilltypecode");
      if (stemp != null) {
        if ((cbilltype != null) && (!cbilltype.equals(stemp.trim()))) {
          continue;
        }

        pinfo = getUIPluginsInfo(XMLUtil.getChildNodeOf(nd, "uiplugin"));
        if (pinfo == null)
          continue;
        pinfo.setCbilltypecode(cbilltype);
        pinfo.setExtenduiclassname(uiclassname);
        pinfo.setNodecode(XMLUtil.getChildNodeValueOf(nd, "nodecode"));
        UIPluginMenuInfo[] menus = getMenuInfos(XMLUtil.getChildNodeOf(nd, "menus"));
        pinfo.setMenuinfo(menus);
        listsf.add(pinfo);
      }
    }
    if (listsf.size() <= 0)
      return null;
    return (UIPluginsInfo[])listsf.toArray(new UIPluginsInfo[listsf.size()]);
  }

  private UIPluginsInfo getUIPluginsInfo(Node uiplugin)
  {
    if (uiplugin == null) {
      return null;
    }

    String stemp = XMLUtil.getChildNodeValueOf(uiplugin, "classname");
    if (StringUtil.isEmpty(stemp))
      return null;
    UIPluginsInfo info = new UIPluginsInfo();
    info.setPluginclassname(stemp.trim());
    stemp = XMLUtil.getChildNodeValueOf(uiplugin, "mothed");
    info.setIsExtends((StringUtil.isEmpty(stemp)) ? UFBoolean.FALSE : new UFBoolean(stemp));
    return info;
  }

  private UIPluginMenuInfo[] getMenuInfos(Node menus)
  {
    if (menus == null) {
      return null;
    }
    NodeList nodelist = menus.getChildNodes();

    if (nodelist.getLength() <= 0)
      return null;
    Node nd = null;

    ArrayList listmenuinfo = new ArrayList();
    UIPluginMenuInfo menuinfo = null;
    for (int i = 0; i < nodelist.getLength(); ++i) {
      nd = nodelist.item(i);
      if (nd.getNodeType() != 1)
        continue;
      String stemp = XMLUtil.getChildNodeValueOf(nd, "name");
      if (StringUtil.isEmpty(stemp)) {
        continue;
      }
      menuinfo = new UIPluginMenuInfo();
      menuinfo.setName(stemp);

      stemp = XMLUtil.getChildNodeValueOf(nd, "code");
      menuinfo.setCode((StringUtil.isEmpty(stemp)) ? null : stemp.trim());

      stemp = XMLUtil.getChildNodeValueOf(nd, "hotkey");
      menuinfo.setHotkey((StringUtil.isEmpty(stemp)) ? null : stemp.trim());

      stemp = XMLUtil.getChildNodeValueOf(nd, "resid");
      menuinfo.setResid((StringUtil.isEmpty(stemp)) ? null : stemp.trim());

      stemp = XMLUtil.getChildNodeValueOf(nd, "parentmenucode");
      menuinfo.setParentmenucode((StringUtil.isEmpty(stemp)) ? null : stemp.trim());

      stemp = XMLUtil.getChildNodeValueOf(nd, "location");
      menuinfo.setLocation((StringUtil.isEmpty(stemp)) ? null : stemp.trim());

      listmenuinfo.add(menuinfo);
    }

    if (listmenuinfo.size() <= 0)
      return null;
    return (UIPluginMenuInfo[])listmenuinfo.toArray(new UIPluginMenuInfo[listmenuinfo.size()]);
  }

  public SmartFieldMeta[] getExtSmartFieldMetas(String prodcode, String cbilltype, String voclassname)
    throws BusinessException
  {
    if ((prodcode == null) || ((cbilltype == null) && (voclassname == null)))
      return null;
    if (m_doc == null)
      return null;
    Element el = XMLUtil.getElement(m_doc, "scm_plugin_" + prodcode.trim().toLowerCase(), 0);
    if (el == null)
      return null;
    NodeList nodelist = el.getElementsByTagName("vo_field_extend");
    if ((nodelist == null) || (nodelist.getLength() <= 0))
      return null;
    Node nd = null;

    ArrayList listsf = new ArrayList();
    for (int i = 0; i < nodelist.getLength(); ++i) {
      nd = nodelist.item(i);
      String stemp = XMLUtil.getChildNodeValueOf(nd, "cbilltypecode");
      if (stemp != null)
        if ((cbilltype == null) || (cbilltype.equals(stemp.trim()))) {
          stemp = XMLUtil.getChildNodeValueOf(nd, "voclassname");
          if (stemp != null)
            if ((voclassname == null) || (voclassname.equals(stemp.trim())))
              getExtSmartFieldMetas(XMLUtil.getChildNodeOf(nd, "fields"), listsf); 
        }
    }
    if (listsf.size() <= 0)
      return null;
    return (SmartFieldMeta[])listsf.toArray(new SmartFieldMeta[listsf.size()]);
  }

  private ArrayList<SmartFieldMeta> getExtSmartFieldMetas(Node fields, ArrayList<SmartFieldMeta> listret)
    throws BusinessException
  {
    if (fields == null)
      return listret;
    NodeList nodelist = fields.getChildNodes();

    if (nodelist.getLength() <= 0)
      return listret;
    Node nd = null;

    for (int i = 0; i < nodelist.getLength(); ++i) {
      nd = nodelist.item(i);
      if (nd.getNodeType() == 1) {
        String stemp = XMLUtil.getChildNodeValueOf(nd, "vofieldname");
        if (StringUtil.isEmpty(stemp))
          throw new BusinessException("erro: vofieldname is null ");
        SmartFieldMeta sf = new SmartFieldMeta();
        sf.setName(stemp.trim());
        sf.setLabel(stemp.trim());

        stemp = XMLUtil.getChildNodeValueOf(nd, "dbfieldname");
        sf.setColumn((StringUtil.isEmpty(stemp)) ? sf.getName() : stemp);

        stemp = XMLUtil.getChildNodeValueOf(nd, "vofieldtype");
        if (StringUtil.isEmpty(stemp))
          throw new BusinessException("erro: vofieldtype is null ");
        sf.setType(Integer.parseInt(stemp.trim()));

        stemp = XMLUtil.getChildNodeValueOf(nd, "dbfieldtype");
        if (StringUtil.isEmpty(stemp))
          throw new BusinessException("erro: dbfieldtype is null ");
        sf.setDbType(Integer.parseInt(stemp.trim()));

        stemp = XMLUtil.getChildNodeValueOf(nd, "persistence");
        if (StringUtil.isEmpty(stemp))
          throw new BusinessException("erro: persistence is null ");
        sf.setPersistence(stemp.trim().toUpperCase().equals("Y"));

        stemp = XMLUtil.getChildNodeValueOf(nd, "length");
        sf.setLength((StringUtil.isEmpty(stemp)) ? 20 : Integer.parseInt(stemp.trim()));

        stemp = XMLUtil.getChildNodeValueOf(nd, "allownull");
        sf.setAllowNull((StringUtil.isEmpty(stemp)) ? true : stemp.trim().toUpperCase().equals("Y"));

        stemp = XMLUtil.getChildNodeValueOf(nd, "precision");
        sf.setPrecision((StringUtil.isEmpty(stemp)) ? 0 : Integer.parseInt(stemp.trim()));

        listret.add(sf);
      }
    }
    return listret;
  }

  public static ScmPluginXML getInstance()
  {
    if (scmpluginxml == null) {
      scmpluginxml = new ScmPluginXML();
    }
    return scmpluginxml;
  }

  public static void main(String[] args) throws Exception
  {
    getInstance().getExtSmartFieldMetas("ic", "4C", "nc.vo.ic.pub.bill.GeneralBillItemVO");
  }

  private static ICache getPluginCache() {
    CacheConfig config = new CacheConfig();

    config.setRegionName("scmplugin");
    config.setCacheType(5);

    ICache cache = CacheManager.getInstance().getCache(config);

    return cache;
  }

  private static void retrieveDoc() {
    try {
      if (RuntimeEnv.getInstance().isRunningInServer()) {
        m_doc = getScmPluginXML();
      }
      else {
        Object cacheDoc = getPluginCache().get("scmplugin_xml");
        if (null == cacheDoc) {
          ServcallVO[] scd = new ServcallVO[1];
          scd[0] = new ServcallVO();
          scd[0].setBeanName("nc.bs.scm.plugin.PluginXMLSever");
          scd[0].setMethodName("getScmPluginXML");
          scd[0].setParameterTypes(new Class[0]);
          scd[0].setParameter(new Object[0]);
          Object[] otemps = LocalCallService.callEJBService("scmpub", scd);

          if ((otemps != null) && (otemps.length > 0)) {
            m_doc = (Document)otemps[0];
            saveDocToCache();
          }
        }
        else if ("yangbo_has no the scmplugin_yangbo".equals(cacheDoc.toString())) {
          m_doc = null;
        } else {
          m_doc = (Document)cacheDoc;
        }
      }
    } catch (Throwable e) {
      SCMEnv.error(e);
    }
  }

  private static void saveDocToCache()
  {
    if (null != m_doc)
      getPluginCache().put("scmplugin_xml", m_doc);
    else
      getPluginCache().put("scmplugin_xml", "yangbo_has no the scmplugin_yangbo");
  }
}